#include <iostream>
#include <signal.h>
#include "../../comm/log.hpp"
#include "../../comm/httplib.h"
#include "oj_control.hpp"
#include "user_control.hpp"

using namespace httplib;
using namespace ns_control;
using namespace ns_user_control;
using namespace ns_log;

// 全局控制器
static Control ctl;
// 全局控制器指针
static Control *pctl;
// 用户控制器
static UserControl user_ctrl;

// 恢复后台编译运行机器
void Recovery(int signo)
{
    pctl->RecoverAllMachines();
}

void Usage()
{
    std::cout << "Usage: " << "./oj_server " << "port" << std::endl;
}

// 用户注册路由: POST /register
// 请求body: {"username":"zhangsan", "password":"123456", "email":"xxx@example.com"}
// 返回: {"status":0, "msg":"注册成功"} 或 {"status":-1, "msg":"错误信息"}
void HandleRegister(const Request &req, Response &resp)
{
    // 解析请求body
    Json::Reader reader;
    Json::Value req_json;
    if (!reader.parse(req.body, req_json))
    {
        Json::Value resp_json;
        resp_json["status"] = -1;
        resp_json["msg"] = "JSON格式错误";
        resp.set_content(resp_json.toStyledString(), "application/json;charset=utf-8");
        return;
    }

    std::string username = req_json["username"].asString();
    std::string password = req_json["password"].asString();
    std::string email = req_json["email"].asString();

    // 调用用户控制层注册
    std::string error_msg;
    Json::Value resp_json;

    if (user_ctrl.Register(username, password, email, &error_msg))
    {
        resp_json["status"] = 0;
        resp_json["msg"] = "注册成功";
    }
    else
    {
        resp_json["status"] = -1;
        resp_json["msg"] = error_msg;
    }

    resp.set_content(resp_json.toStyledString(), "application/json;charset=utf-8");
}

// 用户登录路由: POST /login
// 请求body: {"username":"zhangsan", "password":"123456"}
// 返回: {"status":0, "token":"xxx", "user":{...}} 或 {"status":-1, "msg":"错误信息"}
void HandleLogin(const Request &req, Response &resp)
{
    Json::Reader reader;
    Json::Value req_json;
    if (!reader.parse(req.body, req_json))
    {
        Json::Value resp_json;
        resp_json["status"] = -1;
        resp_json["msg"] = "JSON格式错误";
        resp.set_content(resp_json.toStyledString(), "application/json;charset=utf-8");
        return;
    }
    std::string username = req_json["username"].asString();
    std::string password = req_json["password"].asString();

    std::string token;
    User user;
    std::string error_msg;
    Json::Value resp_json;

    if (user_ctrl.Login(username, password, &token, &user, &error_msg))
    {
        resp_json["status"] = 0;
        resp_json["token"] = token;
        resp_json["user"]["user_id"] = user.user_id;
        resp_json["user"]["username"] = user.username;
        resp_json["user"]["email"] = user.email;
        resp_json["user"]["role"] = user.role;
        resp_json["user"]["total_submit"] = user.total_submit;
        resp_json["user"]["accepted_count"] = user.accepted_count;
    }
    else
    {
        resp_json["status"] = -1;
        resp_json["msg"] = error_msg;
    }

    resp.set_content(resp_json.toStyledString(), "application/json;charset=utf-8");
}

// 用户登出路由: POST /logout
// 请求header: Authorization: Bearer <token>
void HandleLogout(const Request &req, Response &resp)
{
    // 从header获取token:token属于header中的一个属性
    std::string auth_header = req.get_header_value("Authorization");
    Json::Value resp_json;

    if (auth_header.empty() || auth_header.find("Bearer ") != 0)
    {
        resp_json["status"] = -1;
        resp_json["msg"] = "缺少token";
        resp.set_content(resp_json.toStyledString(), "application/json;charset=utf-8");
        return;
    }

    std::string token = auth_header.substr(7); // 去掉"Bearer ":这是token的标准前缀

    if (user_ctrl.Logout(token))
    {
        resp_json["status"] = 0;
        resp_json["msg"] = "登出成功";
    }
    else
    {
        resp_json["status"] = -1;
        resp_json["msg"] = "登出失败";
    }

    resp.set_content(resp_json.toStyledString(), "application/json;charset=utf-8");
}

// 获取用户信息路由: GET /user/:user_id
// 请求header: Authorization: Bearer <token>
// 返回: {"status":0, "user":{...}} 或 {"status":-1, "msg":"错误信息"}
void HandleGetUserInfo(const Request &req, Response &resp)
{
    // 验证token
    std::string auth_header = req.get_header_value("Authorization");
    Json::Value resp_json;

    if (auth_header.empty() || auth_header.find("Bearer ") != 0)
    {
        resp_json["status"] = -1;
        resp_json["msg"] = "未登录";
        resp.set_content(resp_json.toStyledString(), "application/json;charset=utf-8");
        return;
    }

    std::string token = auth_header.substr(7);
    if (!user_ctrl.ValidateToken(token))
    {
        resp_json["status"] = -1;
        resp_json["msg"] = "token无效";
        resp.set_content(resp_json.toStyledString(), "application/json;charset=utf-8");
        return;
    }

    // 获取要查询的user_id:由前端返回,正则匹配
    int user_id = atoi(req.matches[1].str().c_str());
    User user;

    // 这里实际上并没有直接将用户信息填入html中,而是返回用户信息,将具体的填写工作,交给前端完成
    if (user_ctrl.GetUserProfile(user_id, &user))
    {
        resp_json["status"] = 0;
        resp_json["user"]["user_id"] = user.user_id;
        resp_json["user"]["username"] = user.username;
        resp_json["user"]["email"] = user.email;
        resp_json["user"]["total_submit"] = user.total_submit;
        resp_json["user"]["accepted_count"] = user.accepted_count;
        resp_json["user"]["create_time"] = (Json::Int64)user.create_time;
    }
    else
    {
        resp_json["status"] = -1;
        resp_json["msg"] = "用户不存在";
    }

    resp.set_content(resp_json.toStyledString(), "application/json;charset=utf-8");
}

// 通过前端返回的用户id来确定是哪个用户:其实使用token也是可以的,因为token可以找到id
void HandleGetUserSubmissoion(const Request &req, Response &resp)
{
    // 验证token
    std::string auth_header = req.get_header_value("Authorization");
    Json::Value resp_json;

    if (auth_header.empty() || auth_header.find("Bearer ") != 0)
    {
        resp_json["status"] = -1;
        resp_json["msg"] = "未登录";
        resp.set_content(resp_json.toStyledString(), "application/json;charset=utf-8");
        return;
    }

    std::string token = auth_header.substr(7);
    User current_user; // 当前进行访问操作的用户
    if (!user_ctrl.ValidateToken(token))
    {
        resp_json["status"] = -1;
        resp_json["msg"] = "token无效";
        resp.set_content(resp_json.toStyledString(), "application/json;charset=utf-8");
        return;
    }

    // 获取要查询的user_id:通过正则表达式进行匹配
    int user_id = atoi(req.matches[1].str().c_str());
    std::vector<Submission> submissions;
    // 这里实际上并没有直接将用户信息填入html中,而是返回用户信息,将具体的填写工作,交给前端完成
    // 多个submission,每个submission中有多个信息,使用Json数组,使前端进行列表显示
    if (user_ctrl.GetUserSubmissions(user_id, submissions))
    {
        resp_json["status"] = 0;
        for (int i = 0; i < submissions.size(); i++)
        {
            Json::Value submission_json;
            submission_json["submission_id"] = submissions[i].submission_id;
            submission_json["question_number"] = submissions[i].question_number;
            submission_json["status"] = submissions[i].status;
            submission_json["submit_time"] = submissions[i].submit_time;
            resp_json["submissions"].append(submission_json); // 不要漏掉这里的中括号
        }
    }
    else
    {
        resp_json["status"] = -1;
        resp_json["msg"] = "用户不存在";
    }

    resp.set_content(resp_json.toStyledString(), "application/json;charset=utf-8");
}

// 获取排行榜路由: GET /ranking?limit=100
// 返回: {"status":0, "ranking":[{...}, {...}]}
void HandleGetRanking(const Request &req, Response &resp)
{
    int limit = 100;
    //limit是url参数
    if (req.has_param("limit"))
    {
        limit = atoi(req.get_param_value("limit").c_str()); // 客户端指定查多少:分页参数,一页显示多少
    }

    std::vector<User> ranking;
    Json::Value resp_json;

    if (user_ctrl.GetUserRanking(ranking, limit))
    {
        resp_json["status"] = 0;
        for (size_t i = 0; i < ranking.size(); i++)
        {
            Json::Value user_json;
            user_json["rank"] = (int)(i + 1);
            user_json["user_id"] = ranking[i].user_id;
            user_json["username"] = ranking[i].username;
            user_json["total_submit"] = ranking[i].total_submit;
            user_json["accepted_count"] = ranking[i].accepted_count;
            resp_json["ranking"].append(user_json);
        }
    }
    else
    {
        resp_json["status"] = -1;
        resp_json["msg"] = "获取排行榜失败";
    }

    resp.set_content(resp_json.toStyledString(), "application/json;charset=utf-8");
}

// 修改原有的判题路由，添加用户验证和判题后用户提交数和通过数更改
// POST /judge/:number
// 请求header: Authorization: Bearer <token>
// 请求body: {"code":"...", "input":"..."}
void HandleJudge(const Request &req, Response &resp)
{
    // 1. 验证用户token
    std::string auth_header = req.get_header_value("Authorization");
    Json::Value resp_json;

    if (auth_header.empty() || auth_header.find("Bearer ") != 0)
    {

        resp_json["status"] = 100;
        resp_json["msg"] = "未登录，请先登录";
        resp.set_content(resp_json.toStyledString(), "application/json;charset=utf-8");
        return;
    }

    std::string token = auth_header.substr(7);
    if (!user_ctrl.ValidateToken(token))
    {
        resp_json["status"] = 100;
        resp_json["msg"] = "token无效,请重新登录";
        resp.set_content(resp_json.toStyledString(), "application/json;charset=utf-8");
        return;
    }
    int user_id;
    if (!user_ctrl.MapTokenToId(token, user_id))
    {
        resp_json["status"] = 100;
        resp_json["msg"] = "用户不存在";
        resp.set_content(resp_json.toStyledString(), "application/json;charset=utf-8");
        return;
    }

    // 2.获取题目编号
    std::string number = req.matches[1];
    std::string res;

    // 3.调用判题逻辑
    ctl.Judge(number, req.body, res);
    resp.set_content(res, "application/json;charset=utf-8");
    resp.status = 201;

    // 4. 解析判题结果，更新用户统计
    Json::Reader reader;
    Json::Value result;
    reader.parse(res, result);

    // 这里还需要对判题结果进行额外判断(待完善)
    int status = result["res"].asInt(); // 0表示未通过(原因可能存在多种),1表示AC
    bool accepted = (status == 1);

    // 5. 记录提交并更新统计
    user_ctrl.RecordSubmission(user_id, number, status);
    user_ctrl.UpdateUserStats(user_id, accepted);

    // 6. 返回判题结果
    resp.set_content(res, "application/json;charset=utf-8");
}

void GetOneQuestion(const Request &req, Response &resp)
{
    std::string res;
    std::string number = req.matches[1];
    ctl.OneQuestion(res, number);
    resp.status = 200;
    resp.set_content(res, "text/html;charset=utf-8");
}

void GetAllQuestions(const Request &req, Response &resp)
{
    std::string res;
    ctl.AllQuestions(res);
    // res中为相应的html内容
    resp.set_content(res, "text/html;charset=utf-8");
    resp.status = 200;
}

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Usage();
        return -1;
    }
    EnableConsoleLogStrategy(); // 启动日志,默认向显示器输出
    signal(SIGINT, Recovery);

    Server svr;
    pctl = &ctl;

    // 设置静态资源目录（原有的）
    // 这个是用于自动完成静态文件处理的
    svr.set_base_dir("./wwwroot");

    // ========== 用户管理相关路由 ==========
    svr.Post("/register", HandleRegister); // 用户注册
    svr.Post("/login", HandleLogin);       // 用户登录
    svr.Delete("/logout", HandleLogout);   // 用户登出

    svr.Get(R"(/user/(\d+))", HandleGetUserInfo);               // 获取用户信息
    svr.Get(R"(/submissions/(\d+))", HandleGetUserSubmissoion); // 获取用户信息
    svr.Get("/ranking", HandleGetRanking);                      // 获取排行榜

    // 用户获取题目列表
    svr.Get("/all_questions", GetAllQuestions);

    // 用户获取特定题目
    //  /question/100--正则匹配
    //  R"()" 原生字符串
    svr.Get(R"(/question/(\d+))", GetOneQuestion);

    svr.Post(R"(/judge/(\d+))", HandleJudge);
    svr.listen("0.0.0.0", std::stoi(argv[1]));
    return 0;
}
